package com.supreme.threadserver.controller;

import com.supreme.commonboot.utils.AjaxResp;
import com.supreme.threadserver.service.JucUtilService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.concurrent.*;
import java.util.function.BiConsumer;

@Slf4j
@RestController
@RequestMapping(value = "juc-util")
public class JucUtilController {

    @Resource
    private JucUtilService jucUtilService;

    @Resource
    private ThreadPoolTaskExecutor supremeTaskExecutor;

    @GetMapping(value = "countDownLatch")
    public AjaxResp countDownLatch(@RequestParam(value = "threadCount", defaultValue = "5") int threadCount) {
        final CountDownLatch countDownLatch = new CountDownLatch(threadCount);
        for (int i = 0; i < threadCount; i++) {
            long nextLong = RandomUtils.nextLong(5, 10);
            jucUtilService.countDownLatchDemo(countDownLatch, nextLong);
        }
        try {
            System.out.println("countDownLatch Await");
            countDownLatch.await();
            System.out.println("countDownLatch Finish");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return AjaxResp.instance();
    }

    @GetMapping(value = "cyclicBarrier")
    public AjaxResp cyclicBarrier(@RequestParam(value = "threadCount", defaultValue = "5") int threadCount) {
        final CyclicBarrier cyclicBarrier = new CyclicBarrier(threadCount, () -> {
            System.out.println("CyclicBarrier");
        });
        for (int i = 0; i < threadCount; i++) {
            final long nextLong = RandomUtils.nextLong(1, 10);
            jucUtilService.cyclicBarrierDemo(cyclicBarrier, nextLong);
        }
        System.out.println("CyclicBarrier Finished");

        return AjaxResp.instance();
    }

    @GetMapping(value = "semaphore")
    public AjaxResp semaphore(@RequestParam(value = "threadCount", defaultValue = "5") int threadCount) {
        final Semaphore semaphore = new Semaphore(threadCount);
        for (int i = 0; i < threadCount; i++) {
            final long nextLong = RandomUtils.nextLong(1, 10);
            jucUtilService.semaphoreDemo(semaphore, nextLong);
        }

        return AjaxResp.instance();
    }

    @GetMapping(value = "testCompletableFuture")
    public AjaxResp testCompletableFuture(@RequestParam(value = "threadCount", defaultValue = "5", required = false) int threadCount) {
        CompletableFuture.runAsync(() -> jucUtilService.testCompletableFuture(threadCount));
        return AjaxResp.instance();
    }

    @GetMapping(value = "testCountDownLatch")
    public AjaxResp testCountDownLatch(@RequestParam(value = "threadCount", defaultValue = "2", required = false) int threadCount) {
        CompletableFuture.runAsync(() -> jucUtilService.testCountDownLatch(threadCount));
        return AjaxResp.instance();
    }

    @GetMapping(value = "testCyclicBarrier")
    public AjaxResp testCyclicBarrier(@RequestParam(value = "timeout", defaultValue = "60", required = false) long timeout) {
        CompletableFuture.runAsync(() -> jucUtilService.testCyclicBarrier(timeout));
        return AjaxResp.instance();
    }

    @GetMapping(value = "testSemaphore")
    public AjaxResp testSemaphore(@RequestParam(value = "permits", defaultValue = "1", required = false) int permits,
                                  @RequestParam(value = "timeout", defaultValue = "60", required = false) long timeout) {
        CompletableFuture.runAsync(() -> jucUtilService.testSemaphore(permits, timeout));
        return AjaxResp.instance();
    }

    @GetMapping(value = "testSemaphoreTry")
    public AjaxResp testSemaphoreTry(@RequestParam(value = "permits", defaultValue = "1", required = false) int permits,
                                  @RequestParam(value = "timeout", defaultValue = "60", required = false) long timeout) {
        CompletableFuture.runAsync(() -> jucUtilService.testSemaphoreTry(permits, timeout));
        return AjaxResp.instance();
    }
}
